import Koa from 'koa'
import http from 'http'

// middleware
import SessionMiddleware from '@/middleware/session'
import InitMiddleware from '@/middleware/init'
import LogMiddleware from '@/middleware/log'
import BeforeMiddleware from '@/middleware/before'
import RouterMiddleware from '@/middleware/router'
// handler
import ErrorHandler from '@/handler/error'

class Application{
  app: any
  server: any
  constructor(){
    this.app = new Koa()
    this.register()
    this.server = http.createServer(this.app.callback())
  }
  register(){
    this.middleware()
    this.handler()
  }
  middleware(){
    // ctx上初始化数据
    new SessionMiddleware(this.app)
    new InitMiddleware(this.app)
    new BeforeMiddleware(this.app)
    // 日志
    new LogMiddleware(this.app)
    // 路由
    new RouterMiddleware(this.app)
  }
  handler(){
    new ErrorHandler(this.app)
  }
  watch(port?:number){
    this.server.listen(port)
    return this
  }
  error(){
    this.server.on('error',error => {
      if (error.syscall !== 'listen') {
        throw error
      }
      const addr = this.server.address()
      const { port } = addr || {}
      switch(error.code){
        case 'EACCES':
          console.error(`${ port } requires elevated privileges`)
          process.exit(1)
          break;
        case 'EADDRINUSE':
          console.error(`${ port } is already in use`)
          process.exit(1)
          break
        default:
          throw error
      }
    })
    return this
  }
  listen(){
    this.server.on('listening',() => {
      const addr = this.server.address()
      const { port } = addr || {}
      console.log(`Listening on port ${ port }`)
    })
    return this
  }
}

new Application().watch(8899).listen().error()
